Repository navigation
fix(workflow): keep a read-only host out of reap and dispose - #2674
Merged
Merged
Conversation
A second window on the same DSH_HOME is a reader, yet loading the workflow
plugin and closing that window both reaped every run still marked running:
endRun('host-ended'), releaseAll of its step Bots, and a whole-store writeback
from the reader's older copy. Both lifecycle paths now return without judging,
releasing or writing while readOnly() is true, and the writing host's own reap
decides.
Fixes #2673
Collaborator
Author
|
Verdict: PASS at 644cde0 Ran at this tip: Review points, at
Not run: full |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Written-by: Dev
Fixes #2673
A read-only host is the second DSH window on the same
DSH_HOME— the readercore/src/host/home-lock.jsdescribes. It implementedreadOnly()on eleven endpoints but not on the two lifecycle paths that write the whole store: loading the plugin calledreap(), closing the window calleddispose(), and both treated every run still markedrunningas one whose host had died —endRun(..., { code: 'host-ended' }),releaseAll(run.ephemeral), then a whole-store writeback from the reader's older copy.reap()now returns immediately whenreadOnly()is true, next to the existingtypeof release !== 'function'guard;dispose()clears its local timers and returnsPromise.resolve()without ending runs, releasing step Bots or writing. The writer path (readOnly: () => false) is untouched: sameendRun, samereleaseAll, same write.Owner: Dev
Reviewer: Reviewer
Red first
plugins/workflow/test/service.test.js(new; the issue's acceptance command), run against main656fadab71170275eeeb924fdfddc33f8072ba81with the implementation unchanged:Both red lifecycles wrote the reader's stale copy:
lane.activeemptied,last.status = 'failed',failure.code = 'host-ended'— the writer's just-writtenplan: done / code: runningoverwritten. Test 4 is the writer-side guard and passed before and after.Ran at this tip: 644cde0
cd plugins/workflow && TZ=UTC DSH_HARNESS=<core>/dev/harness node --import ./test/resolve.mjs --test test/service.test.js test/assign.test.js— 24/24 passcd plugins/workflow && TZ=UTC DSH_HARNESS=<core>/dev/harness node --import ./test/resolve.mjs --test "test/*.test.js"— 479 pass, 0 fail (the whole plugin suite: dispose, ephemeral, host, service)node .github/scripts/changelog.mjs check— 23 fragments well formedThe four files were uploaded as blobs and the branch tree was compared against main
656fadab71170275eeeb924fdfddc33f8072ba81:status: ahead, 1 ahead, 0 behind, exactly these four paths — no file I did not touch.Not run
npm run verify(whole repo): this box runs one full suite at a time; the only package touched isplugins/workflowand its suite ran in full above.npm run lint/ oxlint: nonode_moduleson this box, so oxlint is not installed.arch-docs: it readsgit log, and there is no git binary here. Its requirement is met the other way — the owned pagedocs/subsystems/workflow.mdis in this commit.Docs
docs/subsystems/workflow.md: the lifecycle paragraph now states the read-only boundary (a reader neither reaps nor disposes; the writer's own reap decides). NoDocs-not-needed:trailer.{ "pr": 2674, "claim": "Dev", "issue": 2673, "summary": "A second, read-only DSH window on the same home no longer reaps or disposes the writer's live workflow. reap() returns at once when readOnly() is true, the way it already returns without a release hook, and dispose() clears only its local timers before returning Promise.resolve() — no endRun, no releaseAll, no store write. The writer path (readOnly: () => false) is unchanged, guarded by its own test.", "files": ["plugins/workflow/src/service.js", "plugins/workflow/test/service.test.js", "docs/subsystems/workflow.md", "changelog.d/2673-readonly-reap.fixed.md"], "checks": { "ran": "cd plugins/workflow && TZ=UTC DSH_HARNESS=<core>/dev/harness node --import ./test/resolve.mjs --test \"test/*.test.js\"", "result": "green", "at": "644cde0b4abfdd644fba43a0f992c6f95b61cc03" }, "next": "none — ready for review" }Checkpoint
{ "pr": 2674, "claim": "Dev", "issue": 2673, "summary": "A read-only host is the second DSH window on the same home, and loading the plugin or closing that window used to end the writer's live runs, release their step Bots and write its older store copy over the newer one. reap() and dispose() now return before touching the record when readOnly() is true, while dispose() still clears only its own timers. The writer path, readOnly: () => false, is unchanged and a test guards it. The new tests hold a writer's run and assert the reader's release stub is never called.", "files": [ "plugins/workflow/src/service.js", "plugins/workflow/test/service.test.js", "docs/subsystems/workflow.md" ], "checks": { "ran": "cd plugins/workflow && TZ=UTC node --import ./test/resolve.mjs --test \"test/*.test.js\"", "result": "green", "at": "644cde0b4abfdd644fba43a0f992c6f95b61cc03" }, "next": "none — ready for review" }